package com.hex.ds.hdtp.core.app.data.contrast.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.hex.ds.hdtp.core.app.common.entity.BasicContrastInfo;
import com.hex.ds.hdtp.core.app.common.enums.BasicListStatus;
import com.hex.ds.hdtp.core.app.common.enums.CrossDbContrastInfo;
import com.hex.ds.hdtp.core.app.common.enums.CrossDbContrastResultContrastType;
import com.hex.ds.hdtp.core.app.data.contrast.converter.ICrossDbContrastConverter;
import com.hex.ds.hdtp.core.app.data.contrast.dto.CrossDbContrastCommonDto;
import com.hex.ds.hdtp.core.app.data.contrast.dto.CrossDbContrastSingleResultDto;
import com.hex.ds.hdtp.core.app.data.contrast.dto.CrossDbContrastTableStructureDto;
import com.hex.ds.hdtp.core.app.data.contrast.service.IContrastTableStructureService;
import com.hex.ds.hdtp.core.app.data.table.dto.request.TableTransferFieldMapRequestDto;
import com.hex.ds.hdtp.core.app.data.table.dto.response.TableTransferFieldMapResponseDto;
import com.hex.ds.hdtp.core.app.data.table.service.ITableTransferFieldMapService;
import com.hex.ds.hdtp.core.app.metadata.service.ISourceConfInfoService;
import com.hex.ds.hdtp.core.app.metadata.service.ISourceInfoService;
import com.hex.ds.hdtp.core.inf.data.contrast.service.IDataInfoService;
import com.hex.ds.hdtp.core.inf.data.contrast.service.impl.DataInfoSelectHandlerContext;
import com.hex.ds.hdtp.core.inf.metadata.po.SourceConfInfoPo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ContrastTableStructureService implements IContrastTableStructureService {

    private final DataInfoSelectHandlerContext dataInfoSelectHandlerContext;

    private final ICrossDbContrastConverter converter;

    private final ISourceConfInfoService sourceConfInfoService;

    private final ITableTransferFieldMapService tableTransferFieldMapService;

    private final CrossDbContrastCommonService crossDbContrastCommonService;

    private final ISourceInfoService sourceInfoService;

    private static final String COLUMN_NAME = "column_name";

    private IDataInfoService getIDataInfoService(String type) {
        return dataInfoSelectHandlerContext.getDataInfoService(type);
    }

    /*
     * @Method: contrastTableStructure <br>
     * @Param: [contrastCommon, contrastTableStructure] <br>
     * @Return: boolean <br>
     * @Description：表结构对比<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/27 11:06 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public boolean contrastTableStructure(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) {
        try {
            // ① 是否建表
            Boolean createFlag = contrastCreateTable(contrastCommon, contrastTableStructure, runLogPkId);

            // ② 字段总数
            Boolean countFlag = contrastFieldCount(contrastCommon, contrastTableStructure, runLogPkId);

            // ③ 字段名称
            Boolean nameFlag = contrastFieldName(contrastCommon, contrastTableStructure, runLogPkId);

            // ④ 分区字段（）
            Boolean partitionFlag = contrastPartitionField(contrastCommon, contrastTableStructure, runLogPkId);

            // ⑤ 字段类型
            Boolean fieldType = contrastFieldType(contrastCommon, contrastTableStructure, runLogPkId);

            // ⑥ 字段长度（每个字段的长度是否一致）
            Boolean fieldLength = contrastFieldLength(contrastCommon, contrastTableStructure, runLogPkId);

            // ⑦ 数值精度
            Boolean fieldAccuracy = contrastFieldPrecision(contrastCommon, contrastTableStructure, runLogPkId);

            // ⑧ 查询编码格式 不比较
//            contrastEncoded(contrastCommon, contrastTableStructure, runLogPkId);
            return createFlag && countFlag && nameFlag && partitionFlag && fieldLength && fieldType && fieldAccuracy;
        } catch (Exception e) {
            log.error("表结构对比异常：{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * @param contrastCommon
     * @param contrastTableStructure
     * @Method contrastCreateTable
     * @Param
     * @Return boolean
     * @Description 【表结构对比】-是否建表
     * @Author Wang zhihao
     * @Date 2023/7/28 9:58
     * @Version V1.0
     */
    private boolean contrastCreateTable(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) {
        if ("Y".equals(contrastTableStructure.getIsCreateTable())) {
            log.info("【表结构对比】-addContrastResult[是否建表对比] 对比开始");
            //1.表结构对比 是否建表 具体比对逻辑
            CrossDbContrastSingleResultDto singleResultDto = contrastCreateTable(converter.toBasicContrastInfo(contrastCommon));
            //2-1表结构比对失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CREATE_TABLE.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[是否建表对比] 对比失败");
                return false;
            }
            //2-2 表结构比对成功处理（插入比对结果日志）
            log.info("【表结构对比】-[是否建表对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CREATE_TABLE.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    /**
     * @param contrastCommon
     * @param contrastTableStructure
     * @Method contrastFieldCount
     * @Param
     * @Return boolean
     * @Description 【表结构对比】-字段总数
     * @Author Wang zhihao
     * @Date 2023/7/28 9:59
     * @Version V1.0
     */
    private boolean contrastFieldCount(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) {
        if ("Y".equals(contrastTableStructure.getIsContrastFieldCount())) {
            log.info("【表结构对比】-[字段总数对比] 对比开始");
            //1.表结构对比 字段总数 具体比对逻辑
            CrossDbContrastSingleResultDto singleResultDto = contrastFieldCount(converter.toBasicContrastInfo(contrastCommon));
            //2-1表结构比对失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_FIELD_COUNT.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[字段总数对比] 对比失败");
                return false;
            }
            //2-2 表结构比对成功处理（插入比对结果日志）
            log.info("【表结构对比】-[字段总数对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_FIELD_COUNT.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    /**
     * @param contrastCommon
     * @param contrastTableStructure
     * @Method contrastFieldName
     * @Param
     * @Return boolean
     * @Description 【表结构对比】-字段名称
     * @Author Wang zhihao
     * @Date 2023/7/28 9:59
     * @Version V1.0
     */
    private boolean contrastFieldName(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) {
        if ("Y".equals(contrastTableStructure.getIsContrastFieldName())) {
            //1.表结构对比 字段名称 具体比对逻辑
            CrossDbContrastSingleResultDto singleResultDto = contrastFieldNameWithMap(converter.toBasicContrastInfo(contrastCommon), contrastCommon.getTableTransferPkId());
            //2-1表结构比对 字段名称 失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_FIELD_NAME.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[字段名称对比] 对比失败");
                return false;
            }
            //2-1表结构比对 字段名称 成功处理（插入比对结果日志）
            log.info("【表结构对比】-[字段名称对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_FIELD_NAME.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    /**
     * @param contrastCommon
     * @param contrastTableStructure
     * @Method contrastPartitionField
     * @Param
     * @Return boolean
     * @Description 【表结构对比】-分区字段
     * @Author Wang zhihao
     * @Date 2023/7/28 9:59
     * @Version V1.0
     */
    private boolean contrastPartitionField(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) {
        if ("Y".equals(contrastTableStructure.getIsContrastPartitionField())) {
            //1.表结构对比 分区字段 具体比对逻辑
            Boolean flag = contrastPartitionField(converter.toBasicContrastInfo(contrastCommon));
            //2-1表结构比对 分区字段 失败处理（插入比对结果日志）
            if (!flag) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_PARTITION_FIELD.getName(),
                        BasicListStatus.FAIL.name(), "【表结构对比】-[分区字段对比] 对比失败");
                log.error("【表结构对比】-[分区字段对比] 失败");
                return false;
            }
            //2-1表结构比对 分区字段 失败处理（插入比对结果日志）
            log.info("【表结构对比】-[分区字段对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_PARTITION_FIELD.getName(),
                    BasicListStatus.SUCCESS.name(), "");
        }
        return true;
    }

    /**
     * @Method contrastFieldType
     * @Param
     * @Param contrastCommon
     * @Param contrastTableStructure
     * @Param runLogPkId
     * @Return boolean
     * @Description 字段类型对比
     * @Author xin.zhao
     * @Date 2023/9/22 14:22
     * @Version V1.0
     */
    private boolean contrastFieldType(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) throws Exception {
        //1.表结构对比 字段类型对比 具体比对逻辑
        if ("Y".equals(contrastTableStructure.getIsContrastFieldType())) {
            CrossDbContrastSingleResultDto singleResultDto = contrastFieldTypeWithMap(converter.toBasicContrastInfo(contrastCommon), contrastCommon.getTableTransferPkId());
            //2-1表结构比对 字段类型对比 失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_TYPE.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[字段类型对比] 对比失败");
                return false;
            }
            //2-1表结构比对 字段类型对比 失败处理（插入比对结果日志）
            log.info("【表结构对比】-[字段类型对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_TYPE.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    /**
     * @Method contrastFieldLength
     * @Param
     * @Param contrastCommon
     * @Param contrastTableStructure
     * @Param runLogPkId
     * @Return boolean
     * @Description 字段长度对比
     * @Author xin.zhao
     * @Date 2023/9/22 14:22
     * @Version V1.0
     */
    private boolean contrastFieldLength(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) throws Exception {
        if ("Y".equals(contrastTableStructure.getIsContrastFieldLength())) {
            //1.表结构对比 字段长度对比 具体比对逻辑
            CrossDbContrastSingleResultDto singleResultDto = contrastFieldLengthWithMap(converter.toBasicContrastInfo(contrastCommon), contrastCommon.getTableTransferPkId());
            //2-1表结构比对 字段长度对比 失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_LENGTH.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[字段长度对比] 对比失败");
                return false;
            }
            //2-1表结构比对 字段长度对比 成功处理（插入比对结果日志）
            log.info("【表结构对比】-[字段长度对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_LENGTH.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    /**
     * @Method contrastFieldPrecision
     * @Param
     * @Param contrastCommon
     * @Param contrastTableStructure
     * @Param runLogPkId
     * @Return java.lang.Boolean
     * @Description 字段精度对比
     * @Author xin.zhao
     * @Date 2023/9/27 18:04
     * @Version V1.0
     */
    private Boolean contrastFieldPrecision(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) throws Exception {
        if ("Y".equals(contrastTableStructure.getIsContrastFieldPrecision())) {
            //1.表结构对比 字段精度对比 具体比对逻辑
            CrossDbContrastSingleResultDto singleResultDto = contrastFieldAccuracy(converter.toBasicContrastInfo(contrastCommon), contrastCommon.getTableTransferPkId());
            //2-1表结构比对 字段精度对比 失败处理（插入比对结果日志）
            if (!singleResultDto.getResult()) {
                crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_PRECISION.getName(),
                        BasicListStatus.FAIL.name(), singleResultDto.getMessage());
                log.error("【表结构对比】-[字段精度对比] 对比失败");
                return false;
            }
            //2-1表结构比对 字段精度对比 成功处理（插入比对结果日志）
            log.info("【表结构对比】-[字段精度对比] 对比成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.IS_CONTRAST_FIELD_PRECISION.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
        return true;
    }

    private void contrastEncoded(CrossDbContrastCommonDto contrastCommon, CrossDbContrastTableStructureDto contrastTableStructure, String runLogPkId) throws Exception {
        if ("Y".equals(contrastTableStructure.getIsContrastFieldPrecision())) {
            //1.查询编码风格
            CrossDbContrastSingleResultDto singleResultDto = selectEncodingStyle(converter.toBasicContrastInfo(contrastCommon));
            log.info("【表结构对比】-[编码格式] 查询成功");
            crossDbContrastCommonService.addContrastResult(contrastCommon, runLogPkId, CrossDbContrastResultContrastType.ENCODING_FORMAT.getName(),
                    BasicListStatus.SUCCESS.name(), singleResultDto.getMessage());
        }
    }


    /**
     * @param contrastInfo
     * @Method contrastCreateTable
     * @Param
     * @Return java.lang.Boolean
     * @Description 建表对比
     * @Author Wang zhihao
     * @Date 2023/8/17 17:22
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastCreateTable(BasicContrastInfo contrastInfo) {
        try {
            //1.查询源表和目标表 信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            //2.查询比对内容
            Boolean sourceDataInfo = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectTableExist(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            Boolean targetDataInfo = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectTableExist(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            //3.查询结果对比
            if (sourceDataInfo && targetDataInfo) {
                return new CrossDbContrastSingleResultDto(true, "表存在，表迁移已完成");
            }
            return new CrossDbContrastSingleResultDto(false, "目标库表迁移的表不存在");
        } catch (Exception e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("是否建表比对发生异常: {}", e.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }

    /**
     * @param contrastInfo
     * @Method contrastFieldCount
     * @Param
     * @Return java.lang.Boolean
     * @Description 字段总数对比
     * @Author Wang zhihao
     * @Date 2023/8/17 17:32
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastFieldCount(BasicContrastInfo contrastInfo) {
        try {
            //获取源和目标库 具体信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            // 获取源与对比目标类型
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String contrastType = contrastConfInfoPoList.get(0).getSourceType();
            // 获取源与对比目标字段数
            Long sourceDataInfo = getIDataInfoService(sourceType).selectAllFieldNum(
                    contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            Long targetDataInfo = getIDataInfoService(contrastType).selectAllFieldNum(
                    contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            // 如果比对双方不为相同类型且源表是IMPALA(大数据仓库)类型，若对比表中不存在源表的分区同名字段 则IMPALA类型的表长度减n处理
            if (!sourceType.equals(contrastType) && sourceType.equals(CrossDbContrastInfo.IMPALA.getName())) {
                List<String> partitionField = getIDataInfoService(sourceType).selectPartitionField(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
                List<String> allFieldName = getIDataInfoService(contrastType).selectFieldName(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
                sourceDataInfo = dealFieldNum(sourceDataInfo, partitionField, allFieldName);
                // 如果比对双方不为相同类型且对比表是IMPALA(大数据仓库)类型，若源表中不存在对比表的分区同名字段 则IMPALA类型的表长度减n处理
            } else if (!sourceType.equals(contrastType) && (contrastType.equals(CrossDbContrastInfo.IMPALA.getName()) || contrastType.equals(CrossDbContrastInfo.GAUSS.getName()))) {
                List<String> partitionField = getIDataInfoService(contrastType).selectPartitionField(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
                List<String> allFieldName = getIDataInfoService(sourceType).selectFieldName(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
                targetDataInfo = dealFieldNum(targetDataInfo, partitionField, allFieldName);
            }
            //比对结果处理
            if (sourceDataInfo.equals(targetDataInfo)) {
                return new CrossDbContrastSingleResultDto(true, "两表字段数相同");
            }
            return new CrossDbContrastSingleResultDto(false, "两表字段数不同," + "源表字段数：" + sourceDataInfo + ", 目标表字段数：" + targetDataInfo);
        } catch (Exception e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("字段总数比对发生异常: {}", e.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }

    /**
     * @param transferListPkId
     * @Method contrastFieldNameWithMap
     * @Param contrastInfo
     * @Return java.lang.Boolean
     * @Description 根据表迁移记录进行字段映射处理的字段名称对比
     * @Author Wang zhihao
     * @Date 2023/8/30 13:51
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastFieldNameWithMap(BasicContrastInfo contrastInfo, String transferListPkId) {
        try {
            //获取源和目标库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            //获取字段名称
            List<String> sourceDataInfo = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectFieldName(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            List<String> targetDataInfo = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectFieldName(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            // 获取对应的字段映射 重构字段
            sourceDataInfo = fieldNameMapping(transferListPkId, sourceDataInfo, contrastInfo);
            // 获取源与对比目标类型
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String contrastType = contrastConfInfoPoList.get(0).getSourceType();
            // 如果比对双方不为相同类型且源表是IMPALA(大数据仓库)类型，若对比表中不存在源表的分区同名字段 则IMPALA类型的表去掉相应字段
            if (!sourceType.equals(contrastType) && sourceType.equals(CrossDbContrastInfo.IMPALA.getName())) {
                List<String> partitionField = getIDataInfoService(sourceType).selectPartitionField(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
                sourceDataInfo = dealFieldName(sourceDataInfo, targetDataInfo, partitionField);
            } else if (!sourceType.equals(contrastType) && (contrastType.equals(CrossDbContrastInfo.IMPALA.getName()) || contrastType.equals(CrossDbContrastInfo.GAUSS.getName()))) {
                List<String> partitionField = getIDataInfoService(contrastType).selectPartitionField(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
                targetDataInfo = dealFieldName(targetDataInfo, sourceDataInfo, partitionField);
            }
            // 找到两个列表的差异
            List<String> source = new ArrayList<>(CollectionUtils.subtract(sourceDataInfo, targetDataInfo));
            List<String> target = new ArrayList<>(CollectionUtils.subtract(targetDataInfo, sourceDataInfo));
            //比对结果类处理
            if (CollectionUtils.isEmpty(source) && CollectionUtils.isEmpty(target)) {
                return new CrossDbContrastSingleResultDto(true, "字段名匹配");
            } else {
                return new CrossDbContrastSingleResultDto(false, "源表未匹配字段：" + source.toString() + " 目标表未匹配字段：" + target.toString());
            }
        } catch (Exception e) {
            String message = crossDbContrastCommonService.findRootCause(e).getMessage();
            log.error("字段名称比对发生异常: {}", e.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, message);
        }
    }

    /**
     * @param contrastInfo
     * @Method contrastPartitionField
     * @Param
     * @Return java.lang.Boolean
     * @Description 分区字段对比
     * @Author Wang zhihao
     * @Date 2023/8/17 19:38
     * @Version V1.0
     */
    public Boolean contrastPartitionField(BasicContrastInfo contrastInfo) {
        try {
            //获取源和目标库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            //查询分区字段结果
            List<String> sourcePartition = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectPartitionField(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            List<String> targetPartition = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectPartitionField(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            return CollectionUtils.isEqualCollection(sourcePartition, targetPartition);
        } catch (Exception e) {
            log.error("分区字段对比发生异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * @Method contrastFieldTypeWithMap
     * @Param
     * @Param contrastInfo
     * @Param transferListPkId
     * @Return java.lang.Boolean
     * @Description 字段类型比较
     * @Author xin.zhao
     * @Date 2023/9/20 11:35
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastFieldTypeWithMap(BasicContrastInfo contrastInfo, String transferListPkId) {
        try {
            //获取源和目标库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            //查询源和目标 字段类型信息
            List<Map<String, String>> sourceDataInfo = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectAllFieldType(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            List<Map<String, String>> targetDataInfo = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectAllFieldType(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            // 获取对应的字段映射 重构字段
            sourceDataInfo = fieldNameTypeMapping(transferListPkId, sourceDataInfo, contrastInfo);
            // 获取源与对比目标类型
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String contrastType = contrastConfInfoPoList.get(0).getSourceType();
            // 如果比对双方不为相同类型且源表是IMPALA(大数据仓库)类型，若对比表中不存在源表的分区同名字段 则IMPALA类型的表去掉相应字段
            if (!sourceType.equals(contrastType) && sourceType.equals(CrossDbContrastInfo.IMPALA.getName())) {
                List<String> partitionField = getIDataInfoService(sourceType).selectPartitionField(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
                sourceDataInfo = dealFieldNameMap(sourceDataInfo, targetDataInfo, partitionField);
            } else if (!sourceType.equals(contrastType) && (contrastType.equals(CrossDbContrastInfo.IMPALA.getName()) || contrastType.equals(CrossDbContrastInfo.GAUSS.getName()))) {
                List<String> partitionField = getIDataInfoService(contrastType).selectPartitionField(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
                targetDataInfo = dealFieldNameMap(targetDataInfo, sourceDataInfo, partitionField);
            }
            CrossDbContrastSingleResultDto singleResultDto = new CrossDbContrastSingleResultDto(false, "");

            //对比结果类处理
            getContrastMessage(singleResultDto, sourceDataInfo, targetDataInfo, "data_type");
            return singleResultDto;
        } catch (SQLException e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("字段类型比对发生异常: {}", rootCause.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }

    /**
     * @Method contrastFieldLengthWithMap
     * @Param
     * @Param contrastInfo
     * @Param transferListPkId
     * @Return java.lang.Boolean
     * @Description 字段长度比较
     * @Author xin.zhao
     * @Date 2023/9/20 14:28
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastFieldLengthWithMap(BasicContrastInfo contrastInfo, String transferListPkId) {
        try {
            //获取源和目标库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            //查询源和目标的字段长度信息
            List<Map<String, String>> sourceDataInfo = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectAllFieldLength(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            List<Map<String, String>> targetDataInfo = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectAllFieldLength(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            // 当存在表迁移时根据表迁移记录获取对应的字段映射 重构字段
            if (transferListPkId != null) {
                sourceDataInfo = fieldNameLengthMapping(transferListPkId, sourceDataInfo, contrastInfo);
            }
            // 获取源与对比目标类型
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String contrastType = contrastConfInfoPoList.get(0).getSourceType();
            // 如果比对双方不为相同类型且源表是IMPALA(大数据仓库)类型，若对比表中不存在源表的分区同名字段 则IMPALA类型的表去掉相应字段
            if (!sourceType.equals(contrastType) && sourceType.equals(CrossDbContrastInfo.IMPALA.getName())) {
                List<String> partitionField = getIDataInfoService(sourceType).selectPartitionField(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
                sourceDataInfo = dealFieldNameMap(sourceDataInfo, targetDataInfo, partitionField);
            } else if (!sourceType.equals(contrastType) && (contrastType.equals(CrossDbContrastInfo.IMPALA.getName()) || contrastType.equals(CrossDbContrastInfo.GAUSS.getName()))) {
                List<String> partitionField = getIDataInfoService(contrastType).selectPartitionField(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
                targetDataInfo = dealFieldNameMap(targetDataInfo, sourceDataInfo, partitionField);
            }
            //获取两个字段类型映射，舍弃非字符类型
            List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = this.getFieldMaps(transferListPkId, contrastInfo);
            Map<String, String> filedType = tableTransferFieldMaps.stream().collect(Collectors.toMap(TableTransferFieldMapResponseDto::getTargetFieldNameUpper, TableTransferFieldMapResponseDto::getSourceFieldTypeUpper));
            CrossDbContrastSingleResultDto singleResultDto = new CrossDbContrastSingleResultDto(true, "");
            //获取字符类型
            List<String> sumFields = getIDataInfoService(sourceType).getStrDataType(sourceType);
            List<String> contrastFiled = filedType.entrySet().stream().filter(entry -> sumFields.contains(entry.getValue())).map(Map.Entry::getKey).collect(Collectors.toList());
            //筛选掉查询结果集合中非字符类型的元素
            if (!CollUtil.isEmpty(contrastFiled)) {
                List<Map<String, String>> contrastSourceDataInfo = sourceDataInfo.stream().filter(map -> (contrastFiled.contains(map.get(COLUMN_NAME).toUpperCase()) == false ? contrastFiled.contains(map.get(COLUMN_NAME).toLowerCase()) : contrastFiled.contains(map.get(COLUMN_NAME).toUpperCase()))).collect(Collectors.toList());
                List<Map<String, String>> contrastTargetDataInfo = targetDataInfo.stream().filter(map -> (contrastFiled.contains(map.get(COLUMN_NAME).toUpperCase()) == false ? contrastFiled.contains(map.get(COLUMN_NAME).toLowerCase()) : contrastFiled.contains(map.get(COLUMN_NAME).toUpperCase()))).collect(Collectors.toList());

                //对比结果类处理
                getContrastMessage(singleResultDto, contrastSourceDataInfo, contrastTargetDataInfo, "data_length");
            }
            return singleResultDto;
        } catch (Exception e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("字段长度比对发生异常: {}", rootCause.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }

    /**
     * @Method contrastFieldLengthWithMap
     * @Param
     * @Param contrastInfo
     * @Param transferListPkId
     * @Return java.lang.Boolean
     * @Description 字段精度对比
     * @Author xin.zhao
     * @Date 2023/9/27 9:41
     * @Version V1.0
     */
    public CrossDbContrastSingleResultDto contrastFieldAccuracy(BasicContrastInfo contrastInfo, String transferListPkId) {
        try {
            //查询源和目标的库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            // 获取源与对比目标类型
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String contrastType = contrastConfInfoPoList.get(0).getSourceType();
            //获取源和目标 精度信息
            List<Map<String, String>> sourceDataInfo = getIDataInfoService(sourceType)
                    .selectFieldAccuracy(contrastInfo.getSourceCode(), contrastInfo.getSourceSchema(), contrastInfo.getSourceTable());
            List<Map<String, String>> targetDataInfo = getIDataInfoService(contrastType)
                    .selectFieldAccuracy(contrastInfo.getContrastCode(), contrastInfo.getContrastSchema(), contrastInfo.getContrastTable());
            //将源的字段名进行映射
            getMapFieldResult(sourceDataInfo, transferListPkId, COLUMN_NAME, contrastInfo);
            // 获取源的精度字段
            List<String> sumFields = getIDataInfoService(sourceType).getAccuracyDataType(sourceType);
            CrossDbContrastSingleResultDto singleResultDto = new CrossDbContrastSingleResultDto(false, "");
            //将无关字段排除
            List<Map<String, String>> sourceFiledList = getMapExcludeResult(sourceDataInfo, sumFields, transferListPkId, COLUMN_NAME, contrastInfo);
            List<Map<String, String>> targetFiledList = getMapExcludeResult(targetDataInfo, sumFields, transferListPkId, COLUMN_NAME, contrastInfo);

            //结果类处理
            getContrastMessage(singleResultDto, sourceFiledList, targetFiledList, "data_accuracy");
            return singleResultDto;
        } catch (Exception e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("字段精度比对发生异常: {}", rootCause.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }


    public CrossDbContrastSingleResultDto selectEncodingStyle(BasicContrastInfo contrastInfo) {
        try {
            //查询源和目标库表信息
            List<SourceConfInfoPo> sourceConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getSourceCode());
            List<SourceConfInfoPo> contrastConfInfoPoList = sourceConfInfoService.queryListBySourceCode(contrastInfo.getContrastCode());
            String sourceType = sourceConfInfoPoList.get(0).getSourceType();
            String targetType = contrastConfInfoPoList.get(0).getSourceType();
            //查询源和目标编码风格
            String sourceCoding = getIDataInfoService(sourceConfInfoPoList.get(0).getSourceType())
                    .selectCoding(contrastInfo.getSourceCode());
            String targetCoding = getIDataInfoService(contrastConfInfoPoList.get(0).getSourceType())
                    .selectCoding(contrastInfo.getContrastCode());
            return new CrossDbContrastSingleResultDto(true, sourceType + "数据库编码格式" + (StringUtils.isNotBlank(sourceCoding) ? sourceCoding : "暂无") + ", " + targetType + "数据库编码格式" + (StringUtils.isNotBlank(targetCoding) ? targetCoding : "暂无"));
        } catch (Exception e) {
            Throwable rootCause = crossDbContrastCommonService.findRootCause(e);
            log.error("是否建表比对发生异常: {}", e.getMessage(), e);
            return new CrossDbContrastSingleResultDto(false, rootCause.getMessage());
        }
    }

    /**
     * @param transferListPkId
     * @param originalFieldName
     * @param contrastInfo
     * @Method fieldNameMapping
     * @Param
     * @Return java.util.List<java.lang.String>
     * @Description 根据表迁移记录获取对应的字段映射 重构字段
     * @Author Wang zhihao
     * @Date 2023/8/30 16:34
     * @Version V1.0
     */
    public List<String> fieldNameMapping(String transferListPkId, List<String> originalFieldName, BasicContrastInfo contrastInfo) {
        //字段名映射
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = new ArrayList<>();
        if (transferListPkId != null) {
            //如果经历过表迁移，那么就从表迁移里获取字段映射
            TableTransferFieldMapRequestDto tableTransferFieldMapRequestDto = new TableTransferFieldMapRequestDto();
            tableTransferFieldMapRequestDto.setListPkId(transferListPkId);
            tableTransferFieldMaps = tableTransferFieldMapService.queryList(tableTransferFieldMapRequestDto);
        } else {
            //否则就连接表获取字段映射
            tableTransferFieldMaps = sourceInfoService.getFieldMaps(converter.toBasicTransferInfo(contrastInfo));
        }
        //从字段信息中 得到 字段名映射
        Map<String, String> fieldsMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getSourceFieldName, TableTransferFieldMapResponseDto::getTargetFieldName));
        List<String> newFieldsName = new ArrayList<>();
        //遍历源字段名 存在映射关系 进行映射得到目标映射字段名
        for (String fieldName : originalFieldName) {
            newFieldsName.add((fieldsMap.get(fieldName) == null) ? fieldName : fieldsMap.get(fieldName));
        }
        return newFieldsName;
    }

    /**
     * @param fieldNum
     * @param partitionFieldList
     * @param allFieldNameList
     * @Method dealFieldNum
     * @Param
     * @Return java.lang.Long
     * @Description 处理因分区字段场景导致的字段数量问题
     * @Author Wang zhihao
     * @Date 2023/8/22 14:45
     * @Version V1.0
     */
    private Long dealFieldNum(Long fieldNum, List<String> partitionFieldList, List<String> allFieldNameList) {
        for (String partitionField : partitionFieldList) {
            if (!allFieldNameList.contains(partitionField)) {
                fieldNum--;
            }
            for (String allField : allFieldNameList) {
                if (partitionField.equalsIgnoreCase(allField.concat(CrossDbContrastInfo.SUFFIX.getName()))) {
                    fieldNum--;
                }
            }
        }
        return fieldNum;
    }

    /**
     * @param dealFieldList
     * @param referFieldList
     * @Method dealFieldName
     * @Param
     * @Return java.util.List<java.lang.String>
     * @Description 处理因分区字段场景导致的字段问题
     * @Author Wang zhihao
     * @Date 2023/8/22 15:27
     * @Version V1.0
     */
    private List<String> dealFieldName(List<String> dealFieldList, List<String> referFieldList, List<String> partitionFieldList) {
        for (String partitionField : partitionFieldList) {
            if (!referFieldList.contains(partitionField)) {
                dealFieldList.remove(partitionField);
            }
            for (String referField : referFieldList) {
                if (partitionField.equalsIgnoreCase(referField.concat(CrossDbContrastInfo.SUFFIX.getName()))) {
                    dealFieldList.remove(partitionField);
                }
            }
        }
        return dealFieldList;
    }

    /**
     * @Method fieldNameMapping
     * @Param
     * @Param transferListPkId
     * @Param originalFieldName
     * @Return java.util.List<java.lang.String>
     * @Description 根据表迁移记录获取对应的字段映射 重构字段名和字段类型
     * @Author xin.zhao
     * @Date 2023/9/18 15:08
     * @Version V1.0
     */
    public List<Map<String, String>> fieldNameTypeMapping(String transferListPkId, List<Map<String, String>> originalFieldNameTypeList, BasicContrastInfo contrastInfo) {
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = this.getFieldMaps(transferListPkId, contrastInfo);
        //获取字段映射
        Map<String, String> fieldsMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getSourceFieldName, TableTransferFieldMapResponseDto::getTargetFieldName));
        //不同的字段映射
        Map<String, String> filteredMap = fieldsMap.entrySet().stream()
                .filter(entry -> !entry.getKey().equals(entry.getValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        //字段类型映射
        Map<String, String> fieldTypeMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getTargetFieldNameUpper, TableTransferFieldMapResponseDto::getTargetFieldType));

        //修改有映射关系的字段
        if (!filteredMap.isEmpty()) {
            ArrayList<String> filterList = new ArrayList<>(filteredMap.keySet());
            for (Map<String, String> originalFieldNameType : originalFieldNameTypeList) {
                if (filterList.contains(originalFieldNameType.get(COLUMN_NAME))) {
                    originalFieldNameType.put(COLUMN_NAME, filteredMap.get(originalFieldNameType.get(COLUMN_NAME)));
                }
            }
        }
        //修改字段类型
        for (Map<String, String> originalFieldNameType : originalFieldNameTypeList) {
            originalFieldNameType.put("data_type", fieldTypeMap.get(originalFieldNameType.get(COLUMN_NAME).toUpperCase()).toUpperCase());
        }
        return originalFieldNameTypeList;
    }

    private List<Map<String, String>> dealFieldNameMap(List<Map<String, String>> dealFieldList, List<Map<String, String>> referFieldList, List<String> partitionFieldList) {
        for (String partitionField : partitionFieldList) {
            boolean isPartitionFieldFound = checkIsPartitionField(referFieldList, partitionField);

            if (!isPartitionFieldFound) {
                // 删除 dealFieldList 中与 partitionField 匹配的 Map
                Iterator<Map<String, String>> iterator = dealFieldList.iterator();
                while (iterator.hasNext()) {
                    Map<String, String> dealFieldMap = iterator.next();
                    String dealFieldValue = dealFieldMap.get(COLUMN_NAME);
                    if (dealFieldValue != null && partitionField.equalsIgnoreCase(dealFieldValue)) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }
        return dealFieldList;
    }

    private static boolean checkIsPartitionField(List<Map<String, String>> referFieldList, String partitionField) {
        boolean isPartitionFieldFound = false;

        for (Map<String, String> referFieldMap : referFieldList) {
            String referFieldValue = referFieldMap.get(COLUMN_NAME);

            if (referFieldValue != null && partitionField.equalsIgnoreCase(referFieldValue)) {
                isPartitionFieldFound = true;
                break;
            }
            String modifiedReferFieldValue = referFieldMap.get(COLUMN_NAME).concat(CrossDbContrastInfo.SUFFIX.getName());

            if (modifiedReferFieldValue != null && partitionField.equalsIgnoreCase(modifiedReferFieldValue)) {
                isPartitionFieldFound = true;
                break;
            }
        }
        return isPartitionFieldFound;
    }

    /**
     * @Method getContrastMessage
     * @Param
     * @Param singleResultDto
     * @Param sourceMap
     * @Param targetMap
     * @Param set1
     * @Param set2
     * @Param contrastType
     * @Return void
     * @Description 比较set 获取比对差异信息
     * @Author xin.zhao
     * @Date 2023/11/16 14:28
     * @Version V1.0
     */
    public void getContrastMessage(CrossDbContrastSingleResultDto singleResultDto, List<Map<String, String>> contrastSourceDataInfo, List<Map<String, String>> contrastTargetDataInfo, String contrastType) {
        // 将List转TreeSet 并排序Map集合
        Set<Map<String, String>> setSource = toNormalizedSet(contrastSourceDataInfo);
        Set<Map<String, String>> setTarget = toNormalizedSet(contrastTargetDataInfo);

        // 迭代器遍历Map，记录差异
        Iterator<Map<String, String>> iteratorSource = setSource.iterator();
        Iterator<Map<String, String>> iteratorTarget = setTarget.iterator();
        while (iteratorSource.hasNext() && iteratorTarget.hasNext()) {
            Map<String, String> sourceMap = iteratorSource.next();
            Map<String, String> targetMap = iteratorTarget.next();
            if (!sourceMap.equals(targetMap)) {
                singleResultDto.setResult(false);
                singleResultDto.setMessage(sourceMap.toString() + targetMap.toString());
                return;
            }
        }
        singleResultDto.setResult(true);
        singleResultDto.setMessage("两表" + contrastType + "比对成功");
    }

    /**
     * @Method toNormalizedSet
     * @Param originalList
     * @Return java.util.Set<java.util.Map<java.lang.String,java.lang.String>>
     * @Description 将List转TreeSet 并排序Map集合
     * @Author Yin.Yang
     * @Date 2024/3/20 17:49
     * @Version V1.0
     */
    private Set<Map<String, String>> toNormalizedSet(List<Map<String, String>> originalList) {
        return originalList.stream().map(this::mapToLowerCase)
                .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Map::toString))));
    }

    /**
     * @Method mapToLowerCase
     * @Param originalMap
     * @Return java.util.Map<java.lang.String,java.lang.String>
     * @Description 把Map的key和value都转为小写
     * @Author Yin.Yang
     * @Date 2024/3/20 17:30
     * @Version V1.0
     */
    private Map<String, String> mapToLowerCase(Map<String, String> originalMap) {
        Map<String, String> normalizedMap = new HashMap<>();
        originalMap.forEach((key, value) -> normalizedMap.put(key.toLowerCase(), value.toLowerCase()));
        return normalizedMap;
    }

    /**
     * @Method fieldNameLengthMapping
     * @Param
     * @Param transferListPkId
     * @Param originalFieldNameTypeList
     * @Return java.util.List<java.util.Map < java.lang.String, java.lang.String>>
     * @Description 根据表迁移记录获取对应的字段映射 重构字段名和字段长度
     * @Author xin.zhao
     * @Date 2023/9/20 12:09
     * @Version V1.0
     */
    public List<Map<String, String>> fieldNameLengthMapping(String transferListPkId, List<Map<String, String>> originalFieldNameTypeList, BasicContrastInfo contrastInfo) {
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = this.getFieldMaps(transferListPkId, contrastInfo);
        //获取字段映射
        Map<String, String> fieldsMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getSourceFieldName, TableTransferFieldMapResponseDto::getTargetFieldName));
        //不同的字段映射
        Map<String, String> filteredMap = fieldsMap.entrySet().stream()
                .filter(entry -> !entry.getKey().equals(entry.getValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        //字段长度映射
        Map<String, String> fieldLengthMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getTargetFieldNameLower, TableTransferFieldMapResponseDto::getTargetFieldLength));
        //修改有映射关系的字段
        if (!filteredMap.isEmpty()) {
            ArrayList<String> filterList = new ArrayList<>(filteredMap.keySet());
            for (Map<String, String> originalFieldNameType : originalFieldNameTypeList) {
                if (filterList.contains(originalFieldNameType.get(COLUMN_NAME))) {
                    originalFieldNameType.put(COLUMN_NAME, filteredMap.get(originalFieldNameType.get(COLUMN_NAME)));
                }
            }
        }
        //修改字段类型
        for (Map<String, String> originalFieldNameType : originalFieldNameTypeList) {
            originalFieldNameType.put("data_length", fieldLengthMap.get(originalFieldNameType.get(COLUMN_NAME).toUpperCase()));
        }
        return originalFieldNameTypeList;
    }

    /**
     * @Method getMapFieldResult
     * @Param
     * @Param sourceDataInfo
     * @Param transferListPkId
     * @Param colName
     * @Return void
     * @Description 字段名称映射
     * @Author xin.zhao
     * @Date 2023/11/16 14:39
     * @Version V1.0
     */
    public void getMapFieldResult(List<Map<String, String>> sourceDataInfo, String transferListPkId, String colName, BasicContrastInfo contrastInfo) {
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = this.getFieldMaps(transferListPkId, contrastInfo);
        //获取字段映射
        Map<String, String> fieldsNameMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getSourceFieldName, TableTransferFieldMapResponseDto::getTargetFieldName));
        //字段名称不同的字段
        HashMap<String, String> fieldNameMap = new HashMap<>();
        for (Map.Entry<String, String> entry : fieldsNameMap.entrySet()) {
            if (!entry.getKey().equals(entry.getValue())) {
                fieldNameMap.put(entry.getKey(), entry.getValue());
            }
        }
        //字段替换
        for (Map<String, String> map : sourceDataInfo) {
            if (map.containsKey(colName)) {
                String columnName = map.get(colName);
                if (fieldNameMap.containsKey(columnName)) {
                    String replacementValue = fieldNameMap.get(columnName);
                    map.put(colName, replacementValue);
                }
            }
        }
    }

    public List<Map<String, String>> getMapExcludeResult(List<Map<String, String>> sourceDataInfo, List<String> sumFields, String transferListPkId, String colName, BasicContrastInfo contrastInfo) {
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = this.getFieldMaps(transferListPkId, contrastInfo);
        //字段类型映射
        Map<String, String> fieldTypeMap = tableTransferFieldMaps.stream()
                .collect(Collectors.toMap(TableTransferFieldMapResponseDto::getSourceFieldName, TableTransferFieldMapResponseDto::getSourceFieldTypeUpper));
        // 创建一个新的 map 用于排除包含在 excludeList 中的值
        Map<String, String> filteredMap = new HashMap<>();

        for (Map.Entry<String, String> entry : fieldTypeMap.entrySet()) {
            if (sumFields.contains(entry.getValue())) {
                filteredMap.put(entry.getKey(), entry.getValue());
            }
        }
        List<String> accuracyFields = new ArrayList<>(filteredMap.keySet());
        List<Map<String, String>> FiledList = new ArrayList<>();
        //比较精度的源表
        for (Map<String, String> map : sourceDataInfo) {
            if (map.containsKey(colName) && (accuracyFields.contains(map.get(colName).toLowerCase()) == false ? accuracyFields.contains(map.get(colName).toUpperCase()) : accuracyFields.contains(map.get(colName).toLowerCase()))) {
                FiledList.add(map);
            }
        }
        return FiledList;
    }

    public List<TableTransferFieldMapResponseDto> getFieldMaps(String transferListPkId, BasicContrastInfo contrastInfo) {
        List<TableTransferFieldMapResponseDto> tableTransferFieldMaps = new ArrayList<>();
        if (transferListPkId != null) {
            //如果经历了表迁移，那么就从表迁移里获取字段映射
            TableTransferFieldMapRequestDto tableTransferFieldMapRequestDto = new TableTransferFieldMapRequestDto();
            tableTransferFieldMapRequestDto.setListPkId(transferListPkId);
            tableTransferFieldMaps = tableTransferFieldMapService.queryList(tableTransferFieldMapRequestDto);
        } else {
            //否则就连接表获取字段映射
            tableTransferFieldMaps = sourceInfoService.getFieldMaps(converter.toBasicTransferInfo(contrastInfo));
        }
        return tableTransferFieldMaps;
    }
}
